/*
 * @Author: Oscar Pena
 * CS431 2011
 * Description: Presents an interface for Actions within a ProgramFlow to 
 * affect the Finch Robot within the simulation environment.
 * */
package FlowGram.Application.SimulatorWindow.Simulator;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;

import javax.swing.JOptionPane;
import javax.swing.JSplitPane;

import FlowGram.Application.Parser.Controllers.FinchController;
import FlowGram.Application.SimulatorWindow.TerrainEditor.Beeper;
import FlowGram.Application.SimulatorWindow.TerrainEditor.Direction;
import FlowGram.Application.SimulatorWindow.TerrainEditor.Finch;
import FlowGram.Application.SimulatorWindow.TerrainEditor.Terrain;
import FlowGram.Application.SimulatorWindow.TerrainEditor.TerrainImage;
public class SimulationController extends FinchController{
	
	private SimulatorEngineWindow simEngWin;
	private int delay;
	private boolean step;
	private Finch finch;
	private TerrainImage terrainImage;
	private Terrain map;
	private MessageBox messageBox;
	
	public SimulationController() {
		
		this.simEngWin = null;
		this.delay = 50;
		this.step = false;
		this.finch = null;
		this.terrainImage = null;
		this.map = null;
		this.messageBox = null;

	}

	@Override
	public String getName() {
		//@description return the controller's name
		return "SimulationController";
	}

	@Override
	public void resetState() {
		// @Description
		
	}

	@Override
	public boolean isBlocked() {
		// @Descritiption: check if there is a MapObject just in front of the finch. A message will show in the simulation window
		// @Return true if isBlocked, false otherwise
		// @Assumes Finch is already placed in the terrain
		if (finch == null) {
			finch = map.getFinch();
			}
		
		boolean er = map.detectCollision(finch, false);
		messageBox.settext("Command \'isBlocked\' ---> " + er);
		return er;
	}

	@Override
	public boolean isTapped() {
		//@Description: test if the finch is tapped, not fully implemented in the simulation
		//@Returns:	always returns false;
		messageBox.settext("Command \'isTapped\' ---> Finch is not tapped");
		delay();
		return false;
	}

	@Override
	public void moveForward() {
		//@Description: moves forward the finch one tile.
		//@Description: if there is an obstacle in front of the finch the finch will stay at the same position.
		//@Description: the object obstructing the Finch will be turned in red.
		//@Description: an error message will show in the simulation window.
		//@Assumes:	Finch is already in the terrain
		//@Assumes: a terrain is already loaded.
		if (finch==null){
			finch = map.getFinch();
		}

		Graphics2D g2d = (Graphics2D) terrainImage.getGraphics();
		if (map.detectCollision(finch, true) == true){
			//System.out.println(map.toString());
			messageBox.setForeground(Color.red);
			messageBox.settext("Command \'move\' ---> ERROR Collided to a Wall and Cannot Move Forward");
		} else {
			messageBox.settext("Command \'move\' ---> Finch is Moving Forward");
			finch.erase(g2d, terrainImage.getScale());
			finch.moveForward();
		}
		terrainImage.update(g2d);
		delay();
	}
	private int countBeepers(){
		//@Description: calls method countBeepers in the Terrain and returns the returned value
		return map.countBeepers(finch);
	}
	private void delay() {
		//@Description: delays the simulation so the movements can be seen by the in slow motion
		//@Description: also if step is true the program will stop until the dialog box is clicked
		//@Description: this will make the animation step by step possible.
		if (step == true){
			JOptionPane.showMessageDialog(null, "click to Continue : " , "FlowGram Simulation", 1);
		} else {
			
			try {
				Thread.sleep((long) (this.delay * 5));
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	@Override
	public void turnLeft() {
		// TODO Auto-generated method stub
		//simEngWin.settext("Turning Left");
		messageBox.settext("Command \'turnLeft\' ----> Finch is Turning Left");
		if (finch == null){
		    //finch = simEngWin.getCurrentMap().getFinch();
		    finch = map.getFinch();
		    }
		//Graphics2D g2d = (Graphics2D) simEngWin.getTerrainImage().getGraphics();
		Graphics2D g2d = (Graphics2D) terrainImage.getGraphics();
		finch.turnleft();
		//finch.erase(g2d, simEngWin.getTerrainImage().getScale());
		finch.erase(g2d, terrainImage.getScale());
		//simEngWin.getTerrainImage().Draw(g2d);
		terrainImage.update(g2d);
		delay();
	}

	@Override
	public void turnRight() {
		// TODO Auto-generated method stub
		//simEngWin.settext("Turning Right");
		messageBox.settext("Command \'turnright\' ----> Finch is Turning Right");
		if (finch== null){
			finch = map.getFinch();
			}
		Graphics2D g2d = (Graphics2D) terrainImage.getGraphics();
		if (finch.getOrientation() == Direction.NORTH){
			finch.setOrientation(Direction.EAST);
		} else if (finch.getOrientation() == Direction.EAST){
			finch.setOrientation(Direction.SOUTH);
		} else if (finch.getOrientation() == Direction.SOUTH){
			finch.setOrientation(Direction.WEST);
		} else if (finch.getOrientation() == Direction.WEST){
			finch.setOrientation(Direction.NORTH);
		}
		finch.erase(g2d, terrainImage.getScale());
		finch.Draw(g2d, terrainImage.getScale());
		terrainImage.update(g2d);
		delay();
	}

	@Override
	public void setColor(Color c) {
		// TODO Auto-generated method stub
		messageBox.settext("Command \'setColor\' ---> Finch is Changing Color");
		
		if (finch==null) {
			finch = map.getFinch();
		}
		Graphics2D g2d = (Graphics2D) terrainImage.getGraphics();
		finch.setColor(c);
		finch.Draw(g2d, terrainImage.getScale());
		terrainImage.update(g2d);
		delay();
	}

	@Override
	public void setColor(Color c, int time) {
		// TODO Auto-generated method stub
		messageBox.settext("Command \'setColor\' ---> Finch is Changing Color");
		if(finch==null){
			finch = map.getFinch();
		}
		Graphics2D g2d = (Graphics2D) terrainImage.getGraphics();
		finch.setColor(c);
		finch.Draw(g2d, terrainImage.getScale());
		terrainImage.update(g2d);
		delay();
	}

	@Override
	public void chirp(int frequency, int duration) {
		// TODO Auto-generated method stub
		messageBox.settext("Command \'chirp\' ----> Finch is Chirping");
		delay();
	}

	public void setDelay(int value) {
		// TODO Auto-generated method stub
		this.delay = value;
	}
	public void setStep(boolean set) {
		// TODO Auto-generated method stub
		this.step = set;
	}

	public void setTerrain(Terrain map2, JSplitPane splitPaneV, TerrainImage terrainImage2) {
		// TODO Auto-generated method stub
		this.map = map2;
		this.terrainImage = terrainImage2;
	}

	public void setFinch(Finch finch2) {
		// TODO Auto-generated method stub
		this.finch = finch2;
	}

	public void setMessageBox(MessageBox messages) {
		// TODO Auto-generated method stub
		this.messageBox = messages;
	}

	@Override
	public boolean isOnBeeper() {
		// TODO Auto-generated method stub
		int count = countBeepers();
		if (count>0){
				messageBox.settext("Command \'isonbeeper\' -> There are " + count + " Beeper(s) in Tile (" + finch.getPositionX() + "," + finch.getPositionY() + ")");
				delay();
				return true;
			}
		delay();
		return false;
		
	}

	@Override
	public void pickBeeper() {
		// TODO Auto-generated method stub
		Graphics2D g2d = (Graphics2D) terrainImage.getGraphics();
		if(isOnBeeper()==false){
			messageBox.settext("ERROR: There are No Beepers in Tile (" + finch.getPositionX() + "," + finch.getPositionY() + ")");
			delay();
		} else {
			Point p1 = new Point(finch.getPositionX(), finch.getPositionY());
			if (map.removeBeeper(p1) == true){
				terrainImage.update(g2d);
				messageBox.settext("Command \'pickbeeper\' -> A Beeper was successfully removed from tile (" + p1.x+ "," + p1.y + ")" );
				delay();
				}
		}
	}

	@Override
	public void putBeeper(Color c) {
		// TODO Auto-generated method stub
		Graphics2D g2d = (Graphics2D) terrainImage.getGraphics();
			Point p1 = new Point(finch.getPositionX(), finch.getPositionY());
			Beeper b = new Beeper(p1.x, p1.y, c);
			map.addbeeper(b);
			terrainImage.update(g2d);
			messageBox.settext("Comnand \'dropbeeper\' -> Beeper added in tile (" + p1.x + "," + p1.y + ")" );
			delay();
		}
}
